<?php

/**
 * UserIdentity represents the data needed to identity a user.
 * It contains the authentication method that checks if the provided
 * data can identity the user.
 */
class UserIdentity extends CUserIdentity
{
	/**
	 * Authenticates a user.
	 * The example implementation makes sure if the username and password
	 * are both 'demo'.
	 * In practical applications, this should be changed to authenticate
	 * against some persistent user identity storage (e.g. database).
	 * @return boolean whether authentication succeeds.
	 */
	public function authenticate()
	{
		// on test si l'authentification LDAP est activée		
		if ( $options =Yii::app()->params['ldap'] ){
			
			// on récupère les infos du config
			// $options = Yii::app()->params['ldap']
			
			// connection au serveur AD
			$connection = ldap_connect($options['host']);
			
			// définitions d'options
			ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3);
			ldap_set_option($connection, LDAP_OPT_REFERRALS, 0);
			
			// si la connection a réussi
			if( $connection ) {
				try {
					// on fait la liaison sur le serveur
					$bind = ldap_bind($connection, $options['username'].'@'.$options['accountDomainName'], $options['password']);
				} catch (Exception $e){
					echo $e->getMessage();
				}
				
				// liste des attributs à récupérer
				$attributes = array(
					'givenName',
					'userPassword',
					'sn',
					'sAMAccountName',
					'password',
					'mail',
					'userAccountControl',
					'adminCount',
					'memberof',
	//            	'thumbnailphoto'
				);
				// on recherche dans la base
				$search = ldap_search($connection, $options['baseDN'], "sAMAccountName=$this->username", $attributes);
			} else {
				die('ldap connection failed <br/> >>'. __LINE__.' | '.__FILE__.' | '.__METHOD__);
			}
			// on récupère les données
			$result = ldap_get_entries($connection, $search);
			
			// on test si le login est bon
			if( empty($result) ) {
				$this->errorCode=self::ERROR_USERNAME_INVALID;
				return !$this->errorCode;
			}
			
			/*
			 * retrait : utilisateur loggé sur ldap
			// on test le password (nécéssité de '@' : une erreur est levée si le mot de passe est incorrect)
			$testPassword = @ldap_bind($connection, $this->username.'@'.$options['accountDomainName'], $this->password);
			if( !$testPassword ) {
				$this->errorCode = self::ERROR_PASSWORD_INVALID;
				return !$this->errorCode;
			}
			*/
			
			// on supprime le nom et le domaine du DN
			$dn = array_splice(array_reverse(array_splice(ldap_explode_dn($result[0]["dn"],2),2),true),2 );
			$dn = preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", implode('|',$dn));
			
			// gestion des groupes d'acces
			 if ($result[0]["memberof"]){
				foreach($result[0]["memberof"] as $acces){
					$memberexpl= ldap_explode_dn($acces,1);
					($memberexpl[2]!='_Groupes de S\C3\A9curit\C3\A9')? null : $group[]=$memberexpl[0];
				}
			}
			$group = preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $group);
			
			$canEdit = false; // définition du droit d'édition
			
			// on test si l'utilisateur appartiient au group Appl_TabaoNG
			if( is_array($group) && in_array('Appl_TabaoNG', $group) ) {
				$canEdit = true;
			} else {
				// on recherche si l'utilisateur appartient à un groupe ayant accès à Appl_TabaoNG
				$searchGroups = ldap_search(
						$connection,
						$options['baseDN'],
						'(&(objectCategory=group)(memberOf=CN=Appl_TabaoNG,OU=Groupes_Pour_Applications,OU=_Groupes de Sécurité,DC=H7402,DC=PRIV))',
						array('cn')
				);
				
				// on récupère les données
				$resultGroups = ldap_get_entries($connection, $searchGroups);
				
				foreach( $resultGroups as $resultGroup ) {
					// on test si l'utilisateur appartient a un des groups ayant accès à Tabao
					if ( is_array($group) && in_array($resultGroup['cn'][0], $group) ) {
						$canEdit = true;
					}
				}
				
			}
			
			// définition du rôle
			$role = ( isset($result[0]["admincount"][0]) ) ? 'admin' : 'user'; 
			
			// définition du status
			 $status= $this->ADUserAccountControl($result[0]["useraccountcontrol"][0]);
			
			// définition des attributs accessibles par 
			// Yii::app()->user->key
			// public void setState(string $key, mixed $value, mixed $defaultValue=NULL)
			$this->setState('username', strtolower($this->username));
			$this->setState('firstname', $result[0]["sn"][0]);
			$this->setState('lastname', $result[0]["givenname"][0]);
			$this->setState('telephoneNumber', $result[0]["telephoneNumber"][0]);
			$this->setState('email', $result[0]["email"][0]);
			$this->setState('dn', $dn);
			$this->setState('group', $group);
			$this->setState('role', $role);
			$this->setState('canEdit', $canEdit);
			$this->setState('status', $status["ADS_UF_ACCOUNTDISABLE"]);
			
		}else{
			
			$this->setState('username', 'offline');
			$this->setState('firstname', 'offline');
			$this->setState('lastname', 'offline');
			$this->setState('telephoneNumber', '');
			$this->setState('email', 'not@email');
			$this->setState('dn', '');
			$this->setState('group', '');
			$this->setState('role', 'admin');
			$this->setState('canEdit', true);
			$this->setState('status', '');		
			
		}
		$this->setState('application', Yii::app()->name);	
		// renvoie le code erreur correspond à une connection réussie
		$this->errorCode = self::ERROR_NONE;
		return !$this->errorCode;
		
	}
	
	protected function ADUserAccountControl($value) {
	    $userAccountArray = array();
	    if(($value-16777216)>=0){$userAccountArray['ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION']=1;$value-=16777216;}else{$userAccountArray['ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION']=0;}
	    if(($value-8388608)>=0) {$userAccountArray['ADS_UF_PASSWORD_EXPIRED']=1;$value-=8388608;}else{$userAccountArray['ADS_UF_PASSWORD_EXPIRED']=0;}
	    if(($value-4194304)>=0){$userAccountArray['ADS_UF_DONT_REQUIRE_PREAUTH']=1;$value-=4194304;}else{$userAccountArray['ADS_UF_DONT_REQUIRE_PREAUTH']=0;}
	    if(($value-2097152)>=0){$userAccountArray['ADS_UF_USE_DES_KEY_ONLY']=1;$value-=2097152;}else{$userAccountArray['ADS_UF_USE_DES_KEY_ONLY']=0;}
	    if(($value-1048576)>=0){$userAccountArray['ADS_UF_NOT_DELEGATED']=1;$value-=1048576;}else{$userAccountArray['ADS_UF_NOT_DELEGATED']=0;}
	    if(($value-524288)>=0){$userAccountArray['ADS_UF_TRUSTED_FOR_DELEGATION']=1;$value-=524288;}else{$userAccountArray['ADS_UF_TRUSTED_FOR_DELEGATION']=0;}
	    if(($value-262144)>=0){$userAccountArray['ADS_UF_SMARTCARD_REQUIRED']=1;$value-=262144;}else{$userAccountArray['ADS_UF_SMARTCARD_REQUIRED']=0;}
	    if(($value-131072)>=0){$userAccountArray['ADS_UF_MNS_LOGON_ACCOUNT']=1;$value-=131072;}else{$userAccountArray['ADS_UF_MNS_LOGON_ACCOUNT']=0;}
	    if(($value-65536)>=0){$userAccountArray['ADS_UF_DONT_EXPIRE_PASSWD']=1;$value-=65536;}else{$userAccountArray['ADS_UF_DONT_EXPIRE_PASSWD']=0;}
	    if(($value-8192)>=0){$userAccountArray['ADS_UF_SERVER_TRUST_ACCOUNT']=1;$value-=8192;}else{$userAccountArray['ADS_UF_SERVER_TRUST_ACCOUNT']=0;}
	    if(($value-4096)>=0){$userAccountArray['ADS_UF_WORKSTATION_TRUST_ACCOUNT']=1;$value-=4096;}else{$userAccountArray['ADS_UF_WORKSTATION_TRUST_ACCOUNT']=0;}
	    if(($value-2048)>=0){$userAccountArray['ADS_UF_INTERDOMAIN_TRUST_ACCOUNT']=1;$value-=2048;}else{$userAccountArray['ADS_UF_INTERDOMAIN_TRUST_ACCOUNT']=0;}
	    if(($value-512)>=0){$userAccountArray['ADS_UF_NORMAL_ACCOUNT']=1;$value-=512;}else{$userAccountArray['ADS_UF_NORMAL_ACCOUNT']=0;}
	    if(($value-256)>=0){$userAccountArray['ADS_UF_TEMP_DUPLICATE_ACCOUNT']=1;$value-=256;}else{$userAccountArray['ADS_UF_TEMP_DUPLICATE_ACCOUNT']=0;}
	    if(($value-128)>=0){$userAccountArray['ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED']=1;$value-=128;}else{$userAccountArray['ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED']=0;}
	    if(($value-64)>=0){$userAccountArray['ADS_UF_PASSWD_CANT_CHANGE']=1;$value-=64;}else{$userAccountArray['ADS_UF_PASSWD_CANT_CHANGE']=0;}
	    if(($value-32)>=0){$userAccountArray['ADS_UF_PASSWD_NOTREQD']=1;$value-=32;}else{$userAccountArray['ADS_UF_PASSWD_NOTREQD']=0;}
	    if(($value-16)>=0){$userAccountArray['ADS_UF_LOCKOUT']=1;$value-=16;}else{$userAccountArray['ADS_UF_LOCKOUT']=0;}
	    if(($value-8)>=0){$userAccountArray['ADS_UF_HOMEDIR_REQUIRED']=1;$value-=8;}else{$userAccountArray['ADS_UF_HOMEDIR_REQUIRED']=0;}
	    if(($value-2)>=0){$userAccountArray['ADS_UF_ACCOUNTDISABLE']=1;$value-=2;}else{$userAccountArray['ADS_UF_ACCOUNTDISABLE']=0;}
	    if(($value-1)>=0){$userAccountArray['ADS_UF_SCRIPT']=1;$value-=1;}else{$userAccountArray['ADS_UF_SCRIPT']=0;}
	    return $userAccountArray;
	}
}
